package com.lq.common.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Base64;
import java.util.Date;
import java.util.Map;
import java.util.function.Function;

/**
 * JWT工具类
 */
public class JwtUtil {
    
    // JWT密钥 - 使用固定的密钥而不是随机生成
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(
        Base64.getDecoder().decode("ZXhhbXBsZVNlY3JldEtleV9leGFtcGxlU2VjcmV0S2V5X2V4YW1wbGVTZWNyZXRLZXkK")
    );
    
    // Token过期时间（毫秒），这里设置为24小时
    private static final long JWT_EXPIRATION = 24 * 60 * 60 * 1000;
    
    /**
     * 生成JWT Token
     * @param userDetails 用户信息
     * @return JWT Token
     */
    public static String generateToken(Map<String, Object> userDetails) {
        return Jwts.builder()
                .setClaims(userDetails)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION))
                .signWith(SECRET_KEY)
                .compact();
    }
    
    /**
     * 从Token中提取用户名
     * @param token JWT Token
     * @return 用户名
     */
    public static String extractUsername(String token) {
        // 先尝试从subject获取用户名
        String username = extractClaim(token, Claims::getSubject);
        // 如果subject为空，则从claims中获取username字段
        if (username == null || username.isEmpty()) {
            username = extractClaim(token, claims -> claims.get("username", String.class));
        }
        return username;
    }
    
    /**
     * 从Token中提取过期时间
     * @param token JWT Token
     * @return 过期时间
     */
    public static Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }

    
    /**
     * 从Token中提取指定声明
     * @param token JWT Token
     * @param claimsResolver 声明解析器
     * @param <T> 声明类型
     * @return 声明值
     */
    public static <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }
    
    /**
     * 从Token中提取所有声明
     * @param token JWT Token
     * @return 所有声明
     */
    private static Claims extractAllClaims(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(SECRET_KEY)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
    
    /**
     * 检查Token是否过期
     * @param token JWT Token
     * @return 是否过期
     */
    private static Boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }
    
    /**
     * 验证Token
     * @param token JWT Token
     * @param username 用户名
     * @return Token是否有效
     */
    public static Boolean validateToken(String token, String username) {
        final String extractedUsername = extractUsername(token);
        return (extractedUsername != null && extractedUsername.equals(username) && !isTokenExpired(token));
    }

    /**
     * 从Token中提取user ID
     *
     * @param jwt JWT Token
     * @return user ID
     */
    public static Integer extractClaimId(String jwt) {
        return extractClaim(jwt, claims -> claims.get("id", Integer.class));
    }
}